// The module 'vscode' contains the VS Code extensibility API
// Import the module and reference it with the alias vscode in your code below
import * as vscode from 'vscode';
import { syncCode } from './syncCode';
import { componentCompile } from './componentCompile';
import { prebuildDownload } from './prebuildDownload';
import { downloadImage } from './downloadImage';
import { deleteImage } from './deleteImage';
import path from 'path';
import fs from 'fs';
import { ReGenerateImagePanel } from './ReGenerateImage/ReGenerateImagePanel';
import { pushFileToDevice } from './pushFileToDevice/pushFileToDevice';
import { HiLogViewProvider } from './HiLog/HiLogViewProvider';
import { HiLogService } from './HiLog/HiLogService';
import { disposeAllTerminals } from './utils/terminalManager';
import { getComponentCompileDir, getConfigFilePath, getHdcPath } from './utils/commonUtils';
import { openOrCreateCustomizedCommandsFile } from './customizedCommand/openOrCreateCustomizedCommandsFile';
import { executeCustomizedCommand } from './customizedCommand/executeCustomCommand';

// 检查文件夹是否包含 bundle.json
async function hasBundleJson(folderPath: string): Promise<boolean> {
	const targetFile = path.join(folderPath, 'bundle.json');
	try {
	  await fs.promises.access(targetFile, fs.constants.F_OK);
	  return true;
	} catch {
	  return false;
	}
}

// 装饰器提供程序
class BundleIndicatorProvider implements vscode.FileDecorationProvider {
	private _onDidChange = new vscode.EventEmitter<vscode.Uri[]>();
	readonly onDidChangeFileDecorations = this._onDidChange.event;
  
	// 当需要更新装饰时调用
	refresh(uris: vscode.Uri[]) {
	  this._onDidChange.fire(uris);
	}
  
	// 核心装饰逻辑
	async provideFileDecoration(uri: vscode.Uri): Promise<vscode.FileDecoration | undefined> {
		// 只处理文件系统中的文件/文件夹
		if (uri.scheme !== 'file') {
			return;
		}

	  	const stat = await vscode.workspace.fs.stat(uri);
	  
		// 为 bundle.json 文件提供装饰
		if (stat.type === vscode.FileType.File && path.basename(uri.fsPath) === 'bundle.json') {
			return {
			badge: '📦',
			tooltip: 'Bundle JSON File',
			color: new vscode.ThemeColor('charts.orange')
			};
		}
	  
	    // 为包含 bundle.json 的文件夹提供装饰
		if (stat.type === vscode.FileType.Directory) {

            // 检查是否是build目录
			if (path.basename(uri.fsPath) === 'build(component-compile)') {
				// 检查同级目录是否有.repo文件夹
				const parentDir = path.dirname(uri.fsPath);
				try {
					const repoPath = path.join(parentDir, '.repo');
					const repoStat = await vscode.workspace.fs.stat(vscode.Uri.file(repoPath));
					// 如果.repo文件夹存在，则不装饰
					if (repoStat.type === vscode.FileType.Directory) {
						return undefined;
					}
				} catch {
					// .repo不存在，继续装饰
				}
				
				return {
					badge: '🔨',
					tooltip: 'Build Directory',
					color: new vscode.ThemeColor('charts.green'),
					propagate: false
				};
			}
			
			// 检查是否是out目录
			if (path.basename(uri.fsPath) === 'out') {
				// 检查同级目录是否有.repo文件夹
				const parentDir = path.dirname(uri.fsPath);
				
				// 检查父目录名称是否为build
				if (path.basename(parentDir) === 'build') {
					return undefined;
				}
				
				try {
					const repoPath = path.join(parentDir, '.repo');
					const repoStat = await vscode.workspace.fs.stat(vscode.Uri.file(repoPath));
					// 如果.repo文件夹存在，则不装饰
					if (repoStat.type === vscode.FileType.Directory) {
						return undefined;
					}
				} catch {
					// .repo不存在，继续装饰
				}
				
				return {
					badge: '🔨',
					tooltip: 'Out Directory',
					color: new vscode.ThemeColor('charts.green'),
					propagate: false
				};
			}
			
			const hasBundle = await hasBundleJson(uri.fsPath);
			return hasBundle ? {
				badge: '📦',
				tooltip: 'Component Folder with bundle.json',
				color: new vscode.ThemeColor('charts.blue'),
				propagate: false
			} : undefined;
  		}
	  
	  	return undefined;
	}
}

// This method is called when your extension is activated
// Your extension is activated the very first time the command is executed
export function activate(context: vscode.ExtensionContext) {

	// 执行插件初始化
	initializeExtension().catch(error => {
		console.error('Failed to initialize extension:', error);
		vscode.window.showErrorMessage(`Extension initialization failed: ${error instanceof Error ? error.message : String(error)}`);
	});

	const provider = new BundleIndicatorProvider();
	const watcher = vscode.workspace.createFileSystemWatcher('**/bundle.json');
  
	// 注册装饰器
	context.subscriptions.push(
	  vscode.window.registerFileDecorationProvider(provider)
	);
  
	// 监听 bundle.json 变化
	const refreshParentFolder = (uri: vscode.Uri) => {
	  const parentUri = vscode.Uri.file(path.dirname(uri.fsPath));
	  provider.refresh([parentUri]);
	};
  
	watcher.onDidCreate(refreshParentFolder);
	watcher.onDidDelete(refreshParentFolder);
	
	// Use the console to output diagnostic information (console.log) and errors (console.error)
	// This line of code will only be executed once when your extension is activated
	console.log('Congratulations, your extension "component-compile" is now active!');

	// Register HiLog view provider
	const hiLogViewProvider = new HiLogViewProvider(context.extensionUri);
	context.subscriptions.push(
		vscode.window.registerWebviewViewProvider(
			HiLogViewProvider.viewType,
			hiLogViewProvider
		)
	);

	const hiLogService = HiLogService.getInstance();
	context.subscriptions.push({
		dispose: () => {
			// 异步停止设备监控，不等待完成
			void hiLogService.stopDeviceMonitoring();
		}
	});

	// The command has been defined in the package.json file
	// Now provide the implementation of the command with registerCommand
	// The commandId parameter must match the command field in package.json
	context.subscriptions.push(vscode.commands.registerCommand('component-compile.syncCode', (...args: any[]) => {
		syncCode(args);
	}));
	
	context.subscriptions.push(vscode.commands.registerCommand('component-compile.componentCompile', (...args: any[]) => {
		componentCompile(context, args);
	}));

	context.subscriptions.push(vscode.commands.registerCommand('component-compile.prebuild-download-option1', (...args: any[]) => {
		prebuildDownload(args, true);
	}));

	context.subscriptions.push(vscode.commands.registerCommand('component-compile.prebuild-download-option2', (...args: any[]) => {
		prebuildDownload(args, false);
	}));

	context.subscriptions.push(vscode.commands.registerCommand('component-compile.pushFileToDevice', (...args: any[]) => {
		pushFileToDevice(args, context);
	}));

	context.subscriptions.push(vscode.commands.registerCommand('component-compile.showHiLog', (...args: any[]) => {
		// Focus the HiLogViewProvider view
		vscode.commands.executeCommand('hiLogView.focus');
	}));

	context.subscriptions.push(vscode.commands.registerCommand('component-compile.componentCompileConfiguration', (...args: any[]) => {
		openOrCreateComponentConfigFile();
	}));
	
	context.subscriptions.push(vscode.commands.registerCommand('component-compile.customizedCommandsConfiguration', (...args: any[]) => {
		openOrCreateCustomizedCommandsFile();
	}));
	
	context.subscriptions.push(vscode.commands.registerCommand('component-compile.customizedCommands', (...args: any[]) => {
		executeCustomizedCommand();
	}));
}

// This method is called when your extension is deactivated
export function deactivate() {
	disposeAllTerminals();
}


/**
 * Opens or creates a componentCompile.json configuration file in the .componentCompile directory
 */
async function openOrCreateComponentConfigFile() {
	const configFilePath = getConfigFilePath();
	const componentCompileDir = getComponentCompileDir();
	
	// Ensure .componentCompile directory exists
	if (!fs.existsSync(componentCompileDir)) {
		fs.mkdirSync(componentCompileDir, { recursive: true });
	}
	
	// Check if file exists
	if (!fs.existsSync(configFilePath)) {
		// Create file with default content including logPath
		const os = require('os');
		const defaultLogPath = path.join(os.homedir(), '.componentCompile', 'logs');
		const defaultContent = JSON.stringify({ 
			ip: "", 
			port: "", 
			logPath: defaultLogPath 
		}, null, 2);
		try {
			fs.writeFileSync(configFilePath, defaultContent, 'utf8');
			vscode.window.showInformationMessage('Created componentCompile.json configuration file in .componentCompile directory');
		} catch (error) {
			vscode.window.showErrorMessage(`Failed to create configuration file: ${error instanceof Error ? error.message : String(error)}`);
			return;
		}
	} else {
		// Check if existing config file has logPath field, add it if missing
		try {
			const configContent = fs.readFileSync(configFilePath, 'utf8');
			const config = JSON.parse(configContent);
			
			if (!config.hasOwnProperty('logPath')) {
				const os = require('os');
				const defaultLogPath = path.join(os.homedir(), '.componentCompile', 'logs');
				config.logPath = defaultLogPath;
				
				const updatedContent = JSON.stringify(config, null, 2);
				fs.writeFileSync(configFilePath, updatedContent, 'utf8');
				vscode.window.showInformationMessage('Updated componentCompile.json configuration file with logPath field');
			}
		} catch (error) {
			vscode.window.showErrorMessage(`Failed to update configuration file: ${error instanceof Error ? error.message : String(error)}`);
		}
	}
	
	// Open the file in editor
	const document = await vscode.workspace.openTextDocument(configFilePath);
	await vscode.window.showTextDocument(document);
}

/**
 * Initializes the extension by setting up necessary directories and tools
 */
async function initializeExtension(): Promise<void> {
	const componentCompileDir = getComponentCompileDir();
	const hdcRepoPath = path.join(componentCompileDir, 'hdc');
	const configFilePath = getConfigFilePath();

	try {
		// 1. Create .componentCompile directory
		if (!fs.existsSync(componentCompileDir)) {
			fs.mkdirSync(componentCompileDir, { recursive: true });
			console.log(`Created directory: ${componentCompileDir}`);
		}

		// 2. Create default config file if it doesn't exist, or update existing one
		if (!fs.existsSync(configFilePath)) {
			const os = require('os');
			const defaultLogPath = path.join(os.homedir(), '.componentCompile', 'logs');
			const defaultContent = JSON.stringify({ 
				ip: "", 
				port: "", 
				logPath: defaultLogPath 
			}, null, 2);
			fs.writeFileSync(configFilePath, defaultContent, 'utf8');
			console.log(`Created config file: ${configFilePath}`);
		} else {
			// Check if existing config file has logPath field, add it if missing
			try {
				const configContent = fs.readFileSync(configFilePath, 'utf8');
				const config = JSON.parse(configContent);
				
				if (!config.hasOwnProperty('logPath')) {
					const os = require('os');
					const defaultLogPath = path.join(os.homedir(), '.componentCompile', 'logs');
					config.logPath = defaultLogPath;
					
					const updatedContent = JSON.stringify(config, null, 2);
					fs.writeFileSync(configFilePath, updatedContent, 'utf8');
					console.log(`Updated config file with logPath: ${configFilePath}`);
				}
			} catch (error) {
				console.error(`Failed to update configuration file: ${error instanceof Error ? error.message : String(error)}`);
			}
		}

		// 3. Clone or update hdc repository
		if (!fs.existsSync(hdcRepoPath)) {
			console.log('Cloning hdc repository...');
			vscode.window.showInformationMessage('Initializing HDC tools, this may take a moment...');
			await executeGitCloneTask(componentCompileDir);
		} else {
			console.log('HDC repository exists, updating...');
			vscode.window.showInformationMessage('Updating HDC tools...');
			await executeGitPullTask(hdcRepoPath);
		}

		// 4. Verify hdc executable exists
		const hdcPath = getHdcPath();
		if (fs.existsSync(hdcPath)) {
			console.log(`HDC executable found at: ${hdcPath}`);
		} else {
			console.warn(`HDC executable not found at: ${hdcPath}`);
		}

	} catch (error) {
		console.error('Extension initialization failed:', error);
		throw error;
	}
}

/**
 * Executes git clone task in background using VS Code task system
 */
async function executeGitCloneTask(workingDir: string): Promise<void> {
	return new Promise<void>((resolve, reject) => {
		const commandStr = 'git clone https://gitee.com/BeicC/hdc.git';
		const taskName = 'HDC Tools Clone';

		const shellExecution = new vscode.ShellExecution(commandStr, {
			cwd: workingDir,
			executable: vscode.env.shell,
			shellArgs: ['-lic']
		});

		const task = new vscode.Task(
			{ type: "shell" },
			vscode.TaskScope.Workspace,
			taskName,
			"Component Compile Init",
			shellExecution
		);

		// Configure task to run in background (hidden)
		task.presentationOptions = {
			reveal: vscode.TaskRevealKind.Never,  // Never show the terminal
			panel: vscode.TaskPanelKind.Shared,
			focus: false,
			clear: false,
			showReuseMessage: false,
			echo: false
		};

		// Listen for task completion
		const endListener = vscode.tasks.onDidEndTaskProcess(event => {
			if (event.execution.task.name === taskName && event.execution.task.source === "Component Compile Init") {
				if (event.exitCode === 0) {
					console.log('Successfully cloned hdc repository');
					vscode.window.showInformationMessage('HDC tools initialized successfully');
					resolve();
				} else {
					console.error(`Git clone failed with exit code ${event.exitCode}`);
					reject(new Error(`Git clone failed with exit code ${event.exitCode}`));
				}
				endListener.dispose();
			}
		});

		// Execute the task
		vscode.tasks.executeTask(task).then(
			() => {
				console.log('Git clone task started');
			},
			(error) => {
				console.error('Failed to start git clone task:', error);
				endListener.dispose();
				reject(error);
			}
		);
	});
}

/**
 * Executes git pull task in background using VS Code task system
 */
async function executeGitPullTask(repoPath: string): Promise<void> {
	return new Promise<void>((resolve, reject) => {
		const commandStr = 'git pull';
		const taskName = 'HDC Tools Update';

		const shellExecution = new vscode.ShellExecution(commandStr, {
			cwd: repoPath,
			executable: vscode.env.shell,
			shellArgs: ['-lic']
		});

		const task = new vscode.Task(
			{ type: "shell" },
			vscode.TaskScope.Workspace,
			taskName,
			"Component Compile Init",
			shellExecution
		);

		// Configure task to run in background (hidden)
		task.presentationOptions = {
			reveal: vscode.TaskRevealKind.Never,  // Never show the terminal
			panel: vscode.TaskPanelKind.Shared,
			focus: false,
			clear: false,
			showReuseMessage: false,
			echo: false
		};

		// Listen for task completion
		const endListener = vscode.tasks.onDidEndTaskProcess(event => {
			if (event.execution.task.name === taskName && event.execution.task.source === "Component Compile Init") {
				if (event.exitCode === 0) {
					console.log('Successfully updated hdc repository');
					vscode.window.showInformationMessage('HDC tools updated successfully');
					resolve();
				} else {
					console.warn(`Git pull completed with exit code ${event.exitCode} (this may be normal if no updates were available)`);
					// Don't treat non-zero exit codes as errors for git pull, as it may just mean no updates
					vscode.window.showInformationMessage('HDC tools are up to date');
					resolve();
				}
				endListener.dispose();
			}
		});

		// Execute the task
		vscode.tasks.executeTask(task).then(
			() => {
				console.log('Git pull task started');
			},
			(error) => {
				console.error('Failed to start git pull task:', error);
				endListener.dispose();
				// Don't reject here, as the tools might still be usable
				console.warn('Git pull failed to start, but existing HDC tools should still be usable');
				resolve();
			}
		);
	});
}
